import random
import re

from flask import request, current_app, jsonify, make_response, session

from info import redis_store, constants, models, db
from info.libs.yuntongxun import sms
from info.models import User
from info.utils.captcha.captcha import captcha
from info.utils.response_code import RET
from . import passport_blue
import datetime


@passport_blue.route('/image_code')
def get_image_code():
    """
    图片验证码
    1. 获取前端产生的图片编号image_code_id(uuid全局唯一标识符)
    2. 产生图片验证码
    3. 利用image_code_id存储产生的图片验证码的内容
    4. 返回图片验证码，修改返回的响应数据类型
    :return:
    """
    # 获取参数图片编号
    image_code_id = request.args.get('imageCodeId')
    # 生成图片验证码
    name, text, image = captcha.generate_captcha()

    print('图片验证码为：' + text)
    # 存储text到redis数据库
    try:
        redis_store.setex('ImageCode_' + image_code_id, constants.IMAGE_CODE_REDIS_EXPIRES, text)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库存储错误')
    else:
        resp = make_response(image)
        resp.headers['Content-Type'] = 'image/jpg'
        return resp
    # return 'image_code'


@passport_blue.route('/sms_code', methods=['POST'])
def get_sms_code():
    """
    短信验证码
    1. 获取参数mobile、图片验证码、图片编号
    2. 检验参数的完整性、手机号合理性（是否注册）、图片验证码是否正确
    3. 利用random生成随机码
    4. 保存生成的随机码进redis数据库
    5. 调用云通讯第三方接口，发送短信验证码
    :return:
    """
#     获取参数
    params_dict = request.json
    mobile = params_dict.get('mobile')
    image_code = params_dict.get('image_code')
    image_code_id = params_dict.get('image_code_id')
#     检验参数的完整性
    if not all([mobile, image_code, image_code_id]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')
    # check mobile's value
    if not re.match(r'1[3456789][0-9]{9}$', mobile):
        return jsonify(errno=RET.DATAERR, errmsg='手机号输入不正确')

    #  whether mobile register
    try:
        user = models.User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='手机号查询失败')
    else:
        if user:
            return jsonify(errno=RET.DATAEXIST, errmsg='手机号已注冊')

    # get real_image_code, to compare with image_code
    try:
        real_image_code = redis_store.get('ImageCode_' + image_code_id)
    #     删除real_image_code
        redis_store.delete('ImageCode_' + image_code_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='获取真实的验证码错误')

    if not real_image_code:
        return jsonify(errno=RET.DATAERR, errmsg='验证码已过期')
    if real_image_code.lower() != str(image_code).lower():
        return jsonify(errno=RET.DATAERR, errmsg='输入的验证码不正确')
    # 生成随机6位短信验证码
    smsCode = '%06d' % random.randint(0, 999999)
    print('短信验证码为:' + smsCode)

#   save smsCode, to verify when register
    try:
        redis_store.setex('SmsCode_' + mobile, constants.SMS_CODE_REDIS_EXPIRES, smsCode)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='短信验证码存储失败')

    # 发送随机短信验证码
    result = sms.CCP().send_template_sms(mobile, [smsCode, constants.SMS_CODE_REDIS_EXPIRES / 60], 1)
    # 检验发送是否成功
    if result == 0:
        return jsonify(errno=RET.OK, errmsg='发送成功')
    else:
        return jsonify(errno=RET.DATAERR, errmsg='短信验证码发送失败')


@passport_blue.route('/register', methods=['POST'])
def register():
    """
    register user
    1. 获取参数mobile  sms_code  password
    2. 检验参数的完整性，手机号的合理性，短信验证码是否正确
    3. 提交数据到数据库
    4. 返回结果
    :return:
    """
    # 获取参数
    mobile = request.json.get('mobile')
    sms_code = request.json.get('smscode')
    password = request.json.get('password')
    # 检验参数的完整性
    if not all([mobile, sms_code, password]):
        return jsonify(errno=RET.DATAERR, errmsg='参数不完整')
    # 检验手机号的合理性
    if not re.match(r'1[3456789][0-9]{9}$', mobile):
        return jsonify(errno=RET.DATAERR, errmsg='请输入正确的手机号')
    # 检验短信验证码是否输入正确
    try:
        real_smsCode = redis_store.get('SmsCode_' + mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='获取短信验证码失败')
    # 检验验证码是否过期
    if not real_smsCode:
        return jsonify(errno=RET.DATAERR, errmsg='短信验证码已过期')
    # 检验验证码输入是否正确
    if real_smsCode != sms_code:
        return jsonify(errno=RET.DATAERR, errmsg='验证码输入不正确')
    # 删除短信验证码
    try:
        redis_store.delete('SmsCode_' + mobile)
    except Exception as e:
        current_app.logger.error(e)

    # 提交数据到数据库
    try:
        user = models.User()
        user.mobile = mobile
        user.nick_name = mobile
        user.password = password
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='注册失败')

    session['user_id'] = user.id
    session['mobile'] = user.mobile
    session['nick_name'] = user.mobile

    return jsonify(errno=RET.OK, errmsg='注册成功')


@passport_blue.route('/login', methods=['POST'])
def login():
    """
    登陆
    1. 获取参数mobile、password
    2. 检查参数的完整性[手机号的格式]，验证用户是否已经注册
    3. 根据手机号，查询数据库的密码，验证输入的密码正确性
    4. 设置session
    5. 返回结果
    :return:
    """
    mobile = request.json.get('mobile')
    password = request.json.get('password')
    if not all([mobile, password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')
    # 验证用户是否已经注册
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='用户查询失败')
    # if not user:
    #     return jsonify(errno=RET.NODATA, errmsg='用户未注册')
    # if not user.check_password(password):
    #     return jsonify(errno=RET.LOGINERR, errmsg='用户密码错误')
    if not user or not user.check_password(password):
        return jsonify(errno=RET.LOGINERR, errmsg='用户名或密码错误')

    session['user_id'] = user.id
    session['nick_name'] = user.nick_name
    session['mobile'] = user.mobile
    session['is_admin'] = user.is_admin

    user.last_login = datetime.datetime.now()
    # User.query.filter().paginate(1, 10, False)
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据提交到mysql数据库失败')

    return jsonify(errno=RET.OK, errmsg='OK')


@passport_blue.route('/logout', methods=['POST'])
def logout():
    """
    退出登陆
    1. 清除对应的key在session中的信息
    2. 返回结果
    :return:
    """
    session.pop('user_id', None)
    session.pop('mobile', None)
    session.pop('nick_name', None)

    return jsonify(errno=RET.OK, errmsg='OK')

